﻿using System;
using System.Linq;
using Autofac;
using Microsoft.Phone.Controls;
using WindowsPhoneEssentials.Abstractions;
using WindowsPhoneEssentials.Diagnostics;
using WindowsPhoneEssentials.Storage;
using WindowsPhoneEssentials.Tasks;
using WindowsPhoneEssentials.Threading;
using WindowsPhoneMVC.Framework;
using WindowsPhoneMVC.Navigation;
using Module = Autofac.Module;

namespace WindowsPhoneMVC.Extensions.AutofacIntegration
{
    public class AutofacNavigationApplication : PhoenixApplicationService
    {
        private readonly IContainer container;

        public AutofacNavigationApplication(): base(
            new PhoneApplicationFrameWrapper(new PhoneApplicationFrame()),
            new TransientStore(),
            new DefaultControllerLocator(ApplicationAssembly), 
            new AutofacControllerFactory(),
            new DefaultViewLocator(ApplicationAssembly),
            new PhoneTaskManager(),
            new BackgroundWorker(),
            new DefaultActionResolver())
        {
            var moduleType = typeof (Module);
            var containerBuilder = new ContainerBuilder();

            using (TraceScope.Create(this, TraceLevel.Debug, () => "Scanning for and Registering Autofac Modules"))
            {
                foreach (var module in ApplicationAssembly.GetTypes()
                    .Where(moduleType.IsAssignableFrom)
                    .Select(t => (Module) Activator.CreateInstance(t)))
                {
                    using (TraceScope.Create(this, TraceLevel.Debug, () => string.Format("Registering module {0}", module.GetType().Name)))
                    {
                        containerBuilder.RegisterModule(module);
                    }
                }
            }

            using (TraceScope.Create(this, TraceLevel.Debug, () => "Building Container"))
                container = containerBuilder.Build();
            ((AutofacControllerFactory) ControllerFactory).SetContainer(Container);
        }

        public IContainer Container
        {
            get { return container; }
        }
    }
}
